package org.shunya.duplicatefileperquisitor.searchengine;

import org.shunya.duplicatefileperquisitor.DuplicateFilePerquisitorObservable;
import org.shunya.duplicatefileperquisitor.gui.FileScanningService;
import org.shunya.duplicatefileperquisitor.model.File;
import org.shunya.duplicatefileperquisitor.model.FileGuiAttributes;
import org.shunya.duplicatefileperquisitor.model.FileType;

import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.*;

public class CustomSimpleFileVisitor extends SimpleFileVisitor<Path> {


    private final DuplicateFilePerquisitorObservable observable;
    private final FileGuiAttributes guiAttributes;
    private final Map<Long, File> allOriginalFiles;
    private final Set<File> filesHavingDuplicates;
    private final List<File> duplicateFiles;
    private final Set<Path> excludedPaths;
    private final Set<Path> pathsTraversed;
    private final EnumSet<FileType> fileTypes;

    public CustomSimpleFileVisitor(DuplicateFilePerquisitorObservable observable, FileGuiAttributes guiAttributes, Map<Long, File> allOriginalFiles, Set<File> filesHavingDuplicates, List<File> duplicateFiles, Set<Path> excludedPaths, Set<Path> pathsTraversed, EnumSet<FileType> fileTypes) {
        this.observable = observable;
        this.guiAttributes = guiAttributes;
        this.allOriginalFiles = allOriginalFiles;
        this.filesHavingDuplicates = filesHavingDuplicates;
        this.duplicateFiles = duplicateFiles;
        this.pathsTraversed = pathsTraversed;
        this.fileTypes = fileTypes;
        this.excludedPaths = excludedPaths;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
            throws IOException {
        Objects.requireNonNull(dir);
        Objects.requireNonNull(attrs);
        if (excludedPaths.contains(dir) || pathsTraversed.contains(dir)) {
            return FileVisitResult.SKIP_SUBTREE;
        }
        pathsTraversed.add(dir);
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
        File file = new File(path);
        guiAttributes.setFileName(file.getFileName());
        guiAttributes.setFileNumber(guiAttributes.getFileNumber() + 1);
        observable.setChanged();
        observable.notifyObservers(guiAttributes);
        if (!fileTypes.contains(file.getFileType())) {
            return FileVisitResult.CONTINUE;
        }
        if (allOriginalFiles.containsKey(file.getCRC32Value())) {
            File originalFile = allOriginalFiles.get(file.getCRC32Value());
            if(!duplicateFiles.contains(originalFile)) {
                originalFile.setGroup(filesHavingDuplicates.size() + 1);
                filesHavingDuplicates.add(originalFile);
                duplicateFiles.add(originalFile);
            }
            file.setGroup(originalFile.getGroup());
            duplicateFiles.add(file);
        } else {
            file.setOriginalFile(true);
            allOriginalFiles.put(file.getCRC32Value(), file);
        }
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException e) {
        return FileVisitResult.CONTINUE;
    }
}
